#include "config.h"

#include <gtest/gtest.h>

#include <cctype>
#include <string>

using namespace cfg;

TEST(BuilderTest, SetAndFreeze)
{
    Builder b;
    b.normalize_keys(
        [](std::string_view k)
        {
            std::string out;
            out.reserve(k.size());
            for (char c : k)
                out.push_back(std::tolower(static_cast<unsigned char>(c)));
            return out;
        });

    b.set("db.host", std::string("localhost"))
        .set("db.port", int64_t{5432})
        .set("arr[2].x", std::string("ok"))
        .set("arr[0]", int64_t{7});

    auto fr = b.freeze();
    ASSERT_TRUE(fr.has_value());

    View v(*fr);
    EXPECT_TRUE(v.lookup("db.host").has_value());
    EXPECT_TRUE(v.lookup("db.port").has_value());

    auto x = v.lookup("arr[2].x");
    ASSERT_TRUE(x.has_value());
    auto xs = x->template get<std::string>();
    ASSERT_TRUE(xs.has_value());
    EXPECT_EQ(*xs, "ok");

    auto a0 = v.lookup("arr[0]");
    ASSERT_TRUE(a0.has_value());
    auto a0i = a0->template get<int64_t>();
    ASSERT_TRUE(a0i.has_value());
    EXPECT_EQ(*a0i, 7);

    auto a1 = v.lookup("arr[1]");
    ASSERT_TRUE(a1.has_value());
    auto a1i = a1->template get<int64_t>();
    ASSERT_FALSE(a1i.has_value());
}

// 边界用例：Builder 解析非法下标（缺少键 或 非数字索引）
TEST(BuilderTest, InvalidPathErrors)
{
    Builder b;
    b.set("[0]", int64_t{1})        // 无键直接下标
        .set("arr[x]", int64_t{2}); // 非数字索引

    auto fr = b.freeze();
    ASSERT_FALSE(fr.has_value());

    const auto & errs = fr.error();
    ASSERT_GE(errs.size(), 1u);
    bool has_invalid_path = false;
    for (const auto & e : errs)
    {
        if (e.code == Errc::InvalidPath)
        {
            has_invalid_path = true;
            break;
        }
    }
    EXPECT_TRUE(has_invalid_path);
}